package com.os.data;

import com.os.constant.Sys;
import com.os.model.DataNodeInfo;
import lombok.SneakyThrows;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 风亦未止
 * @date 2023/5/6 15:47
 */
public class DataStore {
    public static ConcurrentHashMap<String, DataNodeInfo> dataNodeStore = new ConcurrentHashMap();

    /**
     * 随机获取一个地址
     *
     * @return
     */
    @SneakyThrows
    public static URI chooseRandomDataServer() {
        String[] strings = dataNodeStore.keySet().toArray(new String[0]);
        String random = strings[new Random().nextInt(strings.length)];
        String ip = Sys.HTTP + random;
        return new URI(ip);
    }

    /**
     * @param exclude 排除这些 节点地址
     * @return
     */
    @SneakyThrows
    public static List<URI> chooseRandomDataServer(int n, List<String> exclude) {
        List<String> random = getRandom(exclude);
        List<URI> res = new ArrayList<>(n);
        if (random.size() < n) {
            throw new Throwable(String.format("数据节点数小于分片数,需要%s个节点,实际可选%s个,将无法上传全部分片~", n, random.size()));
        }
        for (int i = 0; i < n; i++) {
            String ip = Sys.HTTP + random.get(i);
            res.add(new URI(ip));
        }
        return res;
    }

    /**
     * @param exclude 排除这些 节点地址
     * @return
     */
    @SneakyThrows
    public static List<String> chooseRandomDataServerToString(int n, List<String> exclude) {
        List<String> random = getRandom(exclude);
        List<String> res = new ArrayList<>(n);
        if (random.size() < n) {
            throw new Throwable(String.format("数据节点数小于分片数,还需要%s个节点,实际可选%s个,将无法进行数据修复~", n, random.size()));
        }
        for (int i = 0; i < n; i++) {
            res.add(random.get(i));
        }
        return res;
    }

    private static List<String> getRandom(List<String> exclude) {
        List<String> allAddress = new ArrayList<>(dataNodeStore.keySet());
        List<String> random = new ArrayList<>();
        for (String ip : allAddress) {
            if (!exclude.contains(ip)) {
                random.add(ip);
            }
        }
        Collections.shuffle(random);
        return random;
    }
}
